package com.xuexiang.xui_lib.component.status;

import com.xuexiang.xui_lib.ResourceTable;
import com.xuexiang.xui_lib.component.button.SuperButton;
import com.xuexiang.xui_lib.util.LogUtils;
import com.xuexiang.xui_lib.util.TextUtils;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.agp.utils.Color;
import ohos.app.Context;

/**
 * 此容器组件只允许一个子布局
 */
public class StatefulLayout extends DirectionalLayout implements Component.BindStateChangedListener {

    private static final String MSG_ONE_CHILD = "StatefulLayout must have one child!";

    private StateLayoutConfig mStateConfig = new StateLayoutConfig();
    private AnimatorGroup animatorGroup = new AnimatorGroup();

    private Image stImage;
    private Text stMessage;
    private SuperButton stButton;
    private Component stContainer;          // 布局
    private Component mContentChild;        // 显示的内容
    private RoundProgressBar stProgress;

    private boolean mAnimationEnabled;

    public StatefulLayout(Context context) {
        this(context, null);
    }

    public StatefulLayout(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    public StatefulLayout(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        setBindStateChangedListener(this);
        mAnimationEnabled = mStateConfig.animationEnabled;
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        if (getChildCount() > 1) {
            throw new IllegalStateException(MSG_ONE_CHILD);
        }
        attachTemplate();
    }

    @Override
    public void onComponentUnboundFromWindow(Component component) {
        LogUtils.info("StatusLayout", "onComponentUnboundFromWindow");
    }

    public void setAnimatorEnable(boolean animatorEnable) {
        mAnimationEnabled = animatorEnable;
    }

    public void setInAnimator(AnimatorProperty inAnimator) {
        if (inAnimator == null) {
            return;
        }
        mStateConfig.inAnimation = inAnimator;
    }

    public void setOutAnimator(AnimatorProperty outAnimator) {
        if (outAnimator == null) {
            return;
        }
        mStateConfig.outAnimation = outAnimator;
    }

    public void attachTemplate() {
        mContentChild = getComponentAt(0);
        LayoutScatter.getInstance(getContext()).parse(ResourceTable.Layout_xui_layout_stateful_template, this, true);
        stContainer = findComponentById(ResourceTable.Id_stContainer);
        stProgress = (RoundProgressBar) findComponentById(ResourceTable.Id_st_progress);
        stProgress.setIndeterminate(true);
        stImage = (Image) findComponentById(ResourceTable.Id_st_image);
        stMessage = (Text) findComponentById(ResourceTable.Id_st_message);
        stButton = (SuperButton) findComponentById(ResourceTable.Id_st_button);
    }

    public void showContent() {
        if (mContentChild == null) return;
        if (isAnimationEnabled()) {
            animatorGroup.release();
            animatorGroup.clear();

            mStateConfig.outAnimation.setTarget(stContainer);
            animatorGroup.build().addAnimators(mStateConfig.outAnimation);
            mStateConfig.outAnimation.setStateChangedListener(new StateChangeListenerImpl() {
                @Override
                public void onEnd(Animator animator) {
                    stContainer.setVisibility(HIDE);
                    mContentChild.setVisibility(VISIBLE);
                    mStateConfig.inAnimation.setTarget(mContentChild);
                    animatorGroup.build().addAnimators(mStateConfig.inAnimation);
                    animatorGroup.start();
                }
            });
            animatorGroup.start();
        } else {
            stContainer.setVisibility(Component.HIDE);
            mContentChild.setVisibility(Component.VISIBLE);
        }
    }

    // showLoading
    public void showLoading() {
        showLoading(mStateConfig.loadingMessageRes);
    }

    public void showLoading(int resId) {
        showLoading(getString(resId));
    }

    public void showLoading(String message) {
        showCustom(new CustomStateOptions()
                .message(message)
                .progressColor(new Color(Color.getIntColor("#2A9CDC")))
                .loading());
    }

    // showEmpty
    public void showEmpty() {
        showEmpty(mStateConfig.emptyMessageRes);
    }

    public void showEmpty(int resId) {
        showEmpty(getString(resId));
    }

    public void showEmpty(String message) {
        showCustom(new CustomStateOptions()
                .message(message)
                .image(mStateConfig.emptyImageRes));
    }

    // showError
    public void showError(ClickedListener clickListener) {
        showError(mStateConfig.errorMessageRes, clickListener);
    }

    public void showError(int resId, ClickedListener clickListener) {
        showError(getString(resId), clickListener);
    }

    public void showError(String message, ClickedListener clickListener) {
        showError(message, mStateConfig.retryMessageRes, clickListener);
    }

    public void showError(String message, String buttonText, ClickedListener clickListener) {
        showCustom(new CustomStateOptions()
                .message(message)
                .image(mStateConfig.errorImageRes)
                .buttonText(buttonText)
                .buttonClickListener(clickListener));
    }

    // offline

    /**
     * 显示离线布局（网络异常）
     *
     * @param clickListener
     */
    public void showOffline(ClickedListener clickListener) {
        showOffline(mStateConfig.offlineMessageRes, clickListener);
    }

    public void showOffline(int resId, ClickedListener clickListener) {
        showOffline(getString(resId), clickListener);
    }

    public void showOffline(String message, ClickedListener clickListener) {
        showOffline(message, mStateConfig.retryMessageRes, clickListener);
    }

    public void showOffline(String message, String buttonText, ClickedListener clickListener) {
        showCustom(new CustomStateOptions()
                .message(message)
                .image(mStateConfig.offlineImageRes)
                .buttonText(buttonText)
                .buttonClickListener(clickListener));
    }

    // location off //

    /**
     * 显示定位未打开
     *
     * @param clickListener
     */
    public void showLocationOff(ClickedListener clickListener) {
        showLocationOff(mStateConfig.locationOffMessageRes, clickListener);
    }

    public void showLocationOff(int resId, ClickedListener clickListener) {
        showLocationOff(getString(resId), clickListener);
    }

    public void showLocationOff(String message, ClickedListener clickListener) {
        showLocationOff(message, mStateConfig.retryMessageRes, clickListener);
    }

    public void showLocationOff(String message, String buttonText, ClickedListener clickListener) {
        showCustom(new CustomStateOptions()
                .message(message)
                .image(mStateConfig.locationOffImageRes)
                .buttonText(buttonText)
                .buttonClickListener(clickListener));
    }

    // showCustom
    public void showCustom(final CustomStateOptions options) {
        if (isAnimationEnabled()) {
            animatorGroup.release();
            animatorGroup.clear();
            if (stContainer.getVisibility() == HIDE) {
                mStateConfig.outAnimation.setStateChangedListener(new StateChangeListenerImpl() {
                    @Override
                    public void onEnd(Animator animator) {
                        if (mContentChild != null) {
                            mContentChild.setVisibility(HIDE);
                        }
                        stContainer.setVisibility(VISIBLE);
                        mStateConfig.inAnimation.setTarget(stContainer);
                        animatorGroup.build().addAnimators(mStateConfig.inAnimation);
                        animatorGroup.start();
                    }
                });
                if (mContentChild != null) {
                    mStateConfig.outAnimation.setTarget(mContentChild);
                    animatorGroup.build().addAnimators(mStateConfig.outAnimation);
                    animatorGroup.start();
                }
                state(options);
            } else {
                AnimatorGroup animatorGroup = new AnimatorGroup();
                mStateConfig.outAnimation.setTarget(stContainer);
                mStateConfig.outAnimation.setStateChangedListener(new StateChangeListenerImpl() {
                    @Override
                    public void onEnd(Animator animator) {
                        mStateConfig.inAnimation.setTarget(stContainer);
                        animatorGroup.build().addAnimators(mStateConfig.inAnimation);
                        animatorGroup.start();
                        state(options);
                    }
                });
                animatorGroup.build().addAnimators(mStateConfig.outAnimation);
                animatorGroup.start();
            }
        } else {
            if (mContentChild != null) {
                mContentChild.setVisibility(HIDE);
            }
            stContainer.setVisibility(VISIBLE);
            state(options);
        }
    }


    public boolean isAnimationEnabled() {
        return mAnimationEnabled;
    }

    private String getString(int resId) {
        return getContext().getString(resId);
    }

    private void state(CustomStateOptions options) {
        if (!TextUtils.isEmpty(options.getMessage())) {
            stMessage.setVisibility(VISIBLE);
            stMessage.setText(options.getMessage());
        } else {
            stMessage.setVisibility(HIDE);
        }

        if (options.isLoading()) {
            stProgress.setVisibility(VISIBLE);
            stProgress.setProgressColor(options.getProgressColor());
            stImage.setVisibility(HIDE);
            stButton.setVisibility(HIDE);
        } else {
            stProgress.setVisibility(HIDE);
            if (options.getImageMediaRes() != 0) {
                stImage.setVisibility(VISIBLE);
                stImage.setPixelMap(options.getImageMediaRes());
            } else {
                stImage.setVisibility(HIDE);
            }

            if (options.getClickListener() != null) {
                stButton.setVisibility(VISIBLE);
                stButton.setClickedListener(options.getClickListener());
                if (!TextUtils.isEmpty(options.getButtonText())) {
                    stButton.setText(options.getButtonText());
                }
            } else {
                stButton.setVisibility(HIDE);
            }
        }
    }
}
